package com.ethink.component.warehouse.etonbao;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ethink.component.warehouse.WarehouseInter;
import com.ethink.component.warehouse.enums.EtonbaoServiceNameEnum;
import com.ethink.component.warehouse.model.EtonbaoRequestInfo;
import com.ethink.component.warehouse.properties.ExternalApiEtonbaoProperties;
import com.ethink.warehouse.api.component.info.WarehouseInStockInfo;
import com.ethink.warehouse.api.component.info.WarehouseInStockItemInfo;
import com.ethink.warehouse.api.component.info.WarehouseOutStockInfo;
import com.ethink.warehouse.api.component.info.WarehouseOutStockItemInfo;
import com.ethink.warehouse.api.component.request.*;
import com.ethink.warehouse.api.component.response.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class EtonbaoWarehouseService implements WarehouseInter {
    @Autowired
    private ExternalApiEtonbaoProperties externalApiEtonbaoProperties;

    private final static String WAREHOUSE_CODE = "QDQB";

    @Override
    public WarehouseAddMateResponse addMate(WarehouseAddMateRequest request) {
        return null;
    }

    @Override
    public WarehouseUpdateMateResponse updateMate(WarehouseUpdateMateRequest request) {
        return null;
    }

    @Override
    public WarehouseQueryMateResponse queryMate(WarehouseQueryMateRequest request) {
        return null;
    }

    @Override
    public WarehouseGetMateResponse getMate(WarehouseGetMateRequest request) {
        return null;
    }

    @Override
    public WarehouseQueryInventoryResponse queryInventory(WarehouseQueryInventoryRequest request) {
        return null;
    }

    @Override
    public WarehouseAddInStockResponse addInStockOrder(WarehouseAddInStockRequest request) {
        // 业务参数
        Map<String, Object> bizData = new HashMap<>();
        // 单据主数据
        bizData.put("entryOrderId", request.getOrderNo());
        bizData.put("entryOrderCode", request.getOrderNo());
        bizData.put("omsCode", request.getOwnerCode());
        bizData.put("orderType", request.getInStockType().getCode());
        bizData.put("warehouseCode", WAREHOUSE_CODE);
        bizData.put("purchaseOrderCode", request.getPurchaseOrderCode());
        bizData.put("supplierCode", request.getOwnerCode());
        // 单据明细行数据
        List<Map<String, Object>> itemList = new ArrayList<>();
        for (WarehouseInStockItemInfo itemInfo : request.getItems()) {
            Map<String, Object> itemData = new HashMap<>();
            itemData.put("inventoryType", itemInfo.getInventoryType().getCode());
            itemData.put("itemCode", itemInfo.getMateItemId());
            itemData.put("purchasePrice", 0);
            itemData.put("retailPrice", 0);
            itemData.put("planQty", itemInfo.getPlanQty());
            itemList.add(itemData);
        }
        bizData.put("entryOrderItems", itemList);

        WarehouseAddInStockResponse response = new WarehouseAddInStockResponse();
        // 发送HTTP请求
        JSONObject result = this.sendRequest(request.getOwnerCode(), EtonbaoServiceNameEnum.ENTRYORDER_CREATE, bizData);
        response.setSucceed(result == null ? Boolean.FALSE : Boolean.TRUE);
        return response;
    }

    @Override
    public WarehouseCancelInStockResponse cancelInStockOrder(WarehouseCancelInStockRequest request) {
        // 业务参数
        Map<String, Object> bizData = new HashMap<>();
        bizData.put("omsCode", request.getOwnerCode());
        bizData.put("orderCode", request.getOrderNo());
        bizData.put("orderId", request.getOrderNo());
        bizData.put("orderType", request.getInStockType().getCode());
        bizData.put("warehouseCode", WAREHOUSE_CODE);
        bizData.put("cancelReason", request.getCancelReason());

        WarehouseCancelInStockResponse response = new WarehouseCancelInStockResponse();
        // 发送HTTP请求
        JSONObject result = this.sendRequest(request.getOwnerCode(), EtonbaoServiceNameEnum.ORDER_CANCEL, bizData);
        response.setSucceed(result == null ? Boolean.FALSE : Boolean.TRUE);
        return response;
    }

    @Override
    public WarehouseInStockInfo getInStockOrder(WarehouseGetInStockRequest request) {
        return null;
    }

    @Override
    public WarehouseQueryInStockResponse queryInStockOrder(WarehouseQueryInStockRequest request) {
        return null;
    }

    @Override
    public WarehouseAddOutStockResponse addOutStockOrder(WarehouseAddOutStockRequest request) {
        // 业务参数
        Map<String, Object> bizData = new HashMap<>();
        // 单据主数据
        bizData.put("deliveryOrderId", request.getOrderNo());
        bizData.put("deliveryOrderCode", request.getOrderNo());
        bizData.put("supplierCode", request.getOwnerCode());
        bizData.put("orderType", request.getOutStockType().getCode());
        bizData.put("warehouseCode", WAREHOUSE_CODE);
        // 单据明细行数据
        List<Map<String, Object>> itemList = new ArrayList<>();
        for (WarehouseOutStockItemInfo itemInfo : request.getItems()) {
            Map<String, Object> itemData = new HashMap<>();
            itemData.put("ownerCode", request.getOwnerCode());
            itemData.put("orderLineNo", itemInfo.getOrderLineNo());
            itemData.put("inventoryType", itemInfo.getInventoryType().getCode());
            itemData.put("produceCode", itemInfo.getProduceCode());
            itemData.put("itemCode", itemInfo.getMateItemId());
            itemData.put("planQty", itemInfo.getPlanQty());
            itemData.put("productDate", itemInfo.getProductDate());
            itemData.put("expireDate", itemInfo.getExpireDate());
            itemList.add(itemData);
        }
        bizData.put("stockOutItems", itemList);

        WarehouseAddOutStockResponse response = new WarehouseAddOutStockResponse();
        // 发送HTTP请求
        JSONObject result = this.sendRequest(request.getOwnerCode(), EtonbaoServiceNameEnum.STOCKOUT_CREATE, bizData);
        response.setSucceed(result == null ? Boolean.FALSE : Boolean.TRUE);
        return response;
    }

    @Override
    public WarehouseCancelOutStockResponse cancelOutStockOrder(WarehouseCancelOutStockRequest request) {
        // 业务参数
        Map<String, Object> bizData = new HashMap<>();
        bizData.put("omsCode", request.getOwnerCode());
        bizData.put("orderCode", request.getOrderNo());
        bizData.put("orderId", request.getOrderNo());
        bizData.put("orderType", request.getOutStockType().getCode());
        bizData.put("warehouseCode", WAREHOUSE_CODE);
        bizData.put("cancelReason", request.getCancelReason());

        WarehouseCancelOutStockResponse response = new WarehouseCancelOutStockResponse();
        // 发送HTTP请求
        JSONObject result = this.sendRequest(request.getOwnerCode(), EtonbaoServiceNameEnum.ORDER_CANCEL, bizData);
        response.setSucceed(result == null ? Boolean.FALSE : Boolean.TRUE);
        return response;
    }

    @Override
    public WarehouseOutStockInfo getOutStockOrder(WarehouseGetOutStockRequest request) {
        return null;
    }

    @Override
    public WarehouseQueryOutStockResponse queryOutStockOrder(WarehouseQueryIntStockRequest request) {
        return null;
    }

    @Override
    public Boolean checkSignature(WarehouseCheckSignatureRequest request) {
        EtonbaoRequestInfo requestInfo = getRequestInfoByAppKey(request.getAppKey());
        if (requestInfo == null) {
            return false;
        }
        return generateSign(request.getSignParams(), requestInfo.getAppSecret()).equals(request.getSign());
    }

    private EtonbaoRequestInfo getRequestInfoByAppKey(String appKey) {
        List<EtonbaoRequestInfo> requestInfoList = externalApiEtonbaoProperties
                .getRequestInfoMap()
                .values()
                .stream()
                .filter(e -> e.getAppKey().equals(appKey))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(requestInfoList)) {
            return null;
        }
        return requestInfoList.get(0);
    }


    /**
     * 发送HTTP请求
     * @param ownerCode
     * @param serviceName
     * @param bizData
     * @return
     */
    private JSONObject sendRequest(String ownerCode, EtonbaoServiceNameEnum serviceName, Map<String, Object> bizData) {
        // 业务参数
        JSONObject jsonBizDataObject = JSONUtil.parseObj(bizData);
        String jsonBizDataStr = jsonBizDataObject.toString();
        // 请求公共参数
        EtonbaoRequestInfo requestInfo = externalApiEtonbaoProperties.getRequestInfoMap().get(ownerCode);
        Map<String, String> params = new HashMap<>();
        params.put("app_key", requestInfo.getAppKey());
        params.put("customer_id", requestInfo.getCustomerId());
        params.put("name", serviceName.getCode());
        params.put("data", jsonBizDataStr);
        params.put("format", "json");
        params.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        params.put("version", "");
        params.put("sign", this.generateSign(params, requestInfo.getAppSecret()));

        JSONObject jsonParamsObject = JSONUtil.parseObj(params);
        String jsonParamsStr = jsonParamsObject.toString();
        log.info("请求青岛仓易通宝接口请求参数：{}，{}", externalApiEtonbaoProperties.getRequestUrl(), jsonParamsStr);
        // TODO 发起HTTP请求
//        return new JSONObject();
        // 请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
        // 请求对象
        HttpEntity<String> request = new HttpEntity<>(jsonParamsStr, headers);
        try {
            // 发起请求
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<JSONObject> response = restTemplate.postForEntity(externalApiEtonbaoProperties.getRequestUrl(), request, JSONObject.class);
            if (response.getStatusCode() == HttpStatus.OK) {
                // HTTP请求成功
                JSONObject responseBody = response.getBody();
                log.info("请求青岛仓易通宝接口响应结果：{}", responseBody);
                String responseCode = responseBody.getStr("code");
                if (StringUtils.isNotBlank(responseCode)) {
                    if (responseCode.equals("0")) {
                        // 业务成功
                        return responseBody.getJSONObject("data");
                    } else {
                        return null;
                    }
                } else {
                    return null;
                }
            } else {
                return null;
            }
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 生成签名结果
     * @param signParams
     * @param appSecret
     * @return
     */
    private String generateSign(Map<String, String> signParams, String appSecret) {
        Set<String> keySet = signParams.keySet();
        int keySetSize = keySet.size();
        if (keySetSize <= 0) return "";
        String[] keyArray = keySet.toArray(new String[keySetSize]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder(appSecret);
        for (String k : keyArray) {
            if (k.equals("sign")) {
                continue;
            }
            sb.append(k).append(signParams.get(k));
        }
        sb.append(appSecret);

        String sign = "";
        try {
            sign = DigestUtils.md5DigestAsHex(sb.toString().getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sign.toUpperCase();
    }
}
